package com.jichangxiu.system.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.jichangxiu.common.constant.Constants;
import com.jichangxiu.common.exception.ServiceException;
import com.jichangxiu.common.utils.ConvertUtils;
import com.jichangxiu.system.entity.bo.SysTenantBo;
import com.jichangxiu.system.entity.dto.SysTenantMenuDto;
import com.jichangxiu.system.entity.dto.edit.EditSysTenant;
import com.jichangxiu.system.entity.po.SysMenu;
import com.jichangxiu.system.entity.po.SysTenantMenu;
import com.jichangxiu.system.mapper.SysTenantMenuMapper;
import com.jichangxiu.system.service.SysMenuService;
import com.jichangxiu.system.service.SysTenantMenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SysTenantMenuServiceImpl:
 *
 * @author JiChangXiu
 * @create 2024-06-28 13:44:52
 */
@Slf4j
@Service
public class SysTenantMenuServiceImpl extends MPJBaseServiceImpl<SysTenantMenuMapper, SysTenantMenu> implements SysTenantMenuService {

    @Resource
    private SysMenuService sysMenuService;

    /**
     * 增加 / 修改 / 删除 租户菜单关联列表
     *
     * @param editSysTenant        系统租户
     * @param sysTenantMenuDtoList 租户菜单关联对象列表
     * @return 是否成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addOrDelOrEdit(EditSysTenant editSysTenant, List<SysTenantMenuDto> sysTenantMenuDtoList) {
        SysTenantBo bo = ConvertUtils.convert(editSysTenant, SysTenantBo.class);
        // 租户和菜单的关联关系
        boolean b1 = true;
        boolean b2 = true;
        // 前端传来的角色菜单关联关系
        List<String> menuIdList = editSysTenant.getMenuIdList();
        // 本次要新增的租户菜单关联关系
        List<SysTenantMenu> addSysTenantMenus = new ArrayList<>();
        // 本次要删除的租户菜单关联关系
        List<String> deleteTenantMenuIds = new ArrayList<>();
        if (ObjectUtil.isEmpty(menuIdList) && ObjectUtil.isEmpty(sysTenantMenuDtoList)) {
            // 如果两者都是空的则什么都不做
            log.info("本次无需操作");
        } else if (ObjectUtil.isNotEmpty(menuIdList) && ObjectUtil.isNotEmpty(sysTenantMenuDtoList)) {
            // 如果两者都不是空的
            for (String menuId : menuIdList) {
                // 当前菜单在数据库中是否存在，这里的判断值 默认不存在
                boolean flag = false;
                for (SysTenantMenuDto sysTenantMenuDto : sysTenantMenuDtoList) {
                    if (menuId.equals(sysTenantMenuDto.getMenuId())) {
                        // 代表当前菜单在数据库中已经存在
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                    // 到上个循环结束还不存在，则证明当前菜单在数据库中不存在，需要录入数据库中
                    addSysTenantMenus.add(SysTenantMenu.builder().tenantId(bo.getId()).menuId(menuId).startDate(bo.getStartDate()).endDate(bo.getEndDate()).build());
            }
            // 循环数据库中的值在页面传来的 List 中是否存在，如果不存在，则代表当前值被用户删除
            for (SysTenantMenuDto sysTenantMenuDto : sysTenantMenuDtoList) {
                // 默认不存在
                boolean flag = false;
                for (String menuId : menuIdList) {
                    if (sysTenantMenuDto.getMenuId().equals(menuId)) {
                        // 存在
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                    // 一直到上个循环结束，还是不存在，则证明当前数据库值已被用户删除
                    deleteTenantMenuIds.add(sysTenantMenuDto.getId());
            }
        } else if (ObjectUtil.isEmpty(menuIdList) && ObjectUtil.isNotEmpty(sysTenantMenuDtoList)) {
            // 页面传过来是空的，则需要把数据库中所有已经存在的数据全部删除
            sysTenantMenuDtoList.forEach(sysTenantMenuDto -> deleteTenantMenuIds.add(sysTenantMenuDto.getId()));
        } else if (ObjectUtil.isNotEmpty(menuIdList) && ObjectUtil.isEmpty(sysTenantMenuDtoList)) {
            // 如果页面传过来的不是空的，而数据库中尚未保存数据，则将页面传过来的全部保存
            menuIdList.forEach(menuId -> addSysTenantMenus.add(SysTenantMenu.builder().tenantId(bo.getId()).menuId(menuId).startDate(bo.getStartDate()).endDate(bo.getEndDate()).build()));
        }
        if (ObjectUtil.isNotEmpty(addSysTenantMenus)) {
            List<SysMenu> sysMenuList = sysMenuService.list(new LambdaQueryWrapper<SysMenu>().in(SysMenu::getId, addSysTenantMenus.stream().map(SysTenantMenu::getMenuId).collect(Collectors.toList())));
            if (ObjectUtil.isNotEmpty(sysMenuList)) {
                sysMenuList.forEach(sysMenu -> {
                    String noTenantMenuCodes = Constants.JCX_PROPERTIES.getMenuProperties().getNoTenantMenuCodes();
                    if (StrUtil.isNotBlank(noTenantMenuCodes) && ListUtil.toList(noTenantMenuCodes.split(",")).contains(sysMenu.getCode()))
                        throw new ServiceException("菜单【" + sysMenu.getName() + "】不能分配给租户");
                });
                addSysTenantMenus.forEach(sysTenantMenu -> {
                    SysMenu sysMenu = sysMenuList.stream().filter(menu -> sysTenantMenu.getMenuId().equals(menu.getId())).findFirst().orElse(null);
                    if (ObjectUtil.isNotNull(sysMenu))
                        sysTenantMenu.setType(sysMenu.getType());
                });
            }
            b1 = saveBatch(addSysTenantMenus);
        }
        if (ObjectUtil.isNotEmpty(deleteTenantMenuIds))
            b2 = removeBatchByIds(deleteTenantMenuIds);
        return b1 && b2;
    }

}